package com.fansl.allround.daemon.quartz.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fansl.allround.common.core.constant.enums.ScheduleJobStatusEnum;
import com.fansl.allround.daemon.quartz.dto.ScheduleJobDto;
import com.fansl.allround.daemon.quartz.entity.ScheduleJob;
import com.fansl.allround.daemon.quartz.entity.ScheduleJobLog;
import com.fansl.allround.daemon.quartz.mapper.ScheduleJobLogMapper;
import com.fansl.allround.daemon.quartz.mapper.ScheduleJobMapper;
import com.fansl.allround.daemon.quartz.service.ScheduleJobService;
import com.fansl.allround.daemon.quartz.util.ScheduleJobUtil;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author fansl
 * @Description: TODO
 * @date 2020/1/10 16:56
 */
@Service
public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobMapper, ScheduleJob> implements ScheduleJobService {
    @Autowired
    private Scheduler scheduler;
    @Resource
    private ScheduleJobMapper scheduleJobMapper;
    @Resource
    private ScheduleJobLogMapper scheduleJobLogMapper;

    /**
     * 保存任务
     *
     * @param scheduleJobDto
     * @return
     */
    @Override
    public Boolean saveJob(ScheduleJobDto scheduleJobDto) {
        ScheduleJob job = scheduleJobDto2Bean(scheduleJobDto);
        scheduleJobMapper.insert(job);
        ScheduleJobUtil.createScheduleJob(scheduler, job);
        return true;
    }

    /**
     * dto 转化bean
     *
     * @param scheduleJobDto
     * @return
     */
    private ScheduleJob scheduleJobDto2Bean(ScheduleJobDto scheduleJobDto) {
        ScheduleJob scheduleJob = new ScheduleJob();
        scheduleJob.setJobId(scheduleJobDto.getJobId());
        scheduleJob.setJobName(scheduleJobDto.getJobName());
        scheduleJob.setJobGroup(scheduleJobDto.getJobGroup());
        scheduleJob.setMethodName(scheduleJobDto.getMethodName());
        scheduleJob.setMethodParams(JSONObject.toJSONString(scheduleJobDto.getMethodParams()));
        scheduleJob.setCronExpression(scheduleJobDto.getCronExpression());
        scheduleJob.setMisfirePolicy(scheduleJobDto.getMisfirePolicy().getCode());
        scheduleJob.setConcurrent(scheduleJobDto.isConcurrent() ? 1 : 0);
        scheduleJob.setStatus(scheduleJobDto.getStatus().getCode());
        scheduleJob.setRemark(scheduleJobDto.getRemark());
        return scheduleJob;
    }

    /**
     * 更新任务
     *
     * @param scheduleJobDto
     * @return
     */
    @Override
    public Boolean updateJob(ScheduleJobDto scheduleJobDto) {
        ScheduleJob scheduleJob = scheduleJobDto2Bean(scheduleJobDto);
        int count = scheduleJobMapper.update(scheduleJob,
                Wrappers.<ScheduleJob>lambdaQuery().eq(ScheduleJob::getJobId, scheduleJob.getJobId()));
        if (count > 0) {
            ScheduleJobUtil.updateScheduleJob(scheduler, scheduleJob);
        }
        return true;
    }

    /**
     * 删除任务
     *
     * @param jobId
     * @return
     */
    @Override
    public Boolean deleteJob(Long jobId) {
        ScheduleJob scheduleJob = scheduleJobMapper.selectById(jobId);
        if (ObjectUtil.isNotNull(scheduleJob)) {
            scheduleJobMapper.deleteById(jobId);
            ScheduleJobUtil.deleteSchedulerJob(scheduler, jobId, scheduleJob.getJobGroup());
        }
        return true;
    }

    @Override
    public Boolean runJob(Long jobId) {
        ScheduleJob scheduleJob = scheduleJobMapper.selectById(jobId);
        if (ObjectUtil.isNotNull(scheduleJob)) {
            ScheduleJobUtil.run(scheduler, scheduleJob);
            return true;
        }
        return false;
    }

    /**
     * 暂停任务
     *
     * @param jobId
     * @return
     */
    @Override
    public Boolean pauseJob(Long jobId) {
        ScheduleJob scheduleJob = scheduleJobMapper.selectById(jobId);
        if (ObjectUtil.isNotNull(scheduleJob)) {
            ScheduleJobUtil.pauseJob(scheduler, jobId, scheduleJob.getJobGroup());

            ScheduleJob update = new ScheduleJob();
            update.setJobId(jobId);
            update.setStatus(ScheduleJobStatusEnum.PAUSE.getCode());
            scheduleJobMapper.updateById(update);
        }
        return true;
    }

    /**
     * 恢复任务
     *
     * @param jobId
     * @return
     */
    @Override
    public Boolean resumeJob(Long jobId) {
        ScheduleJob scheduleJob = scheduleJobMapper.selectById(jobId);
        if (ObjectUtil.isNotNull(scheduleJob)) {
            ScheduleJobUtil.resumeJob(scheduler, jobId, scheduleJob.getJobGroup());

            ScheduleJob update = new ScheduleJob();
            update.setJobId(jobId);
            update.setStatus(ScheduleJobStatusEnum.RUNNING.getCode());
            scheduleJobMapper.updateById(update);
        }
        return true;
    }

    /**
     * 保存日志
     *
     * @param scheduleJobLog
     * @return
     */
    @Override
    public Boolean saveJobLog(ScheduleJobLog scheduleJobLog) {
        return scheduleJobLogMapper.insert(scheduleJobLog) > 0;
    }

    /**
     * 查询任务日志详情
     *
     * @param jobLogId
     * @return
     */
    @Override
    public ScheduleJobLog infoLog(Long jobLogId) {
        return scheduleJobLogMapper.selectById(jobLogId);
    }

    /**
     * 查询任务的日志
     *
     * @param jobId
     * @return
     */
    @Override
    public List<ScheduleJobLog> listJobLog(Long jobId) {
        return scheduleJobLogMapper.selectList(Wrappers.<ScheduleJobLog>lambdaQuery()
                .eq(ScheduleJobLog::getJobId, jobId));
    }

    /**
     * 分页查询任务日志
     *
     * @param page
     * @param scheduleJobLog
     * @return
     */
    @Override
    public IPage<ScheduleJobLog> pageJobLog(Page page, ScheduleJobLog scheduleJobLog) {
        return scheduleJobLogMapper.selectPage(page, Wrappers.query(scheduleJobLog));
    }

    /**
     * 更新定时任务的执行情况（状态，执行次数）
     *
     * @param jobId
     * @param update
     * @return
     */
    @Override
    public Boolean updateExecuteDetail(Long jobId, ScheduleJob update) {
        return scheduleJobMapper.updateExecuteDetail(jobId,update)>0;
    }
}
